﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace UniRx
{
	// Token: 0x020001F6 RID: 502
	public sealed class CompositeDisposable : ICollection<IDisposable>, IDisposable, ICancelable, IEnumerable, IEnumerable<IDisposable>
	{
		// Token: 0x06000A86 RID: 2694 RVA: 0x00038378 File Offset: 0x00036778
		public CompositeDisposable()
		{
			this._disposables = new List<IDisposable>();
		}

		// Token: 0x06000A87 RID: 2695 RVA: 0x00038396 File Offset: 0x00036796
		public CompositeDisposable(int capacity)
		{
			if (capacity < 0)
			{
				throw new ArgumentOutOfRangeException("capacity");
			}
			this._disposables = new List<IDisposable>(capacity);
		}

		// Token: 0x06000A88 RID: 2696 RVA: 0x000383C8 File Offset: 0x000367C8
		public CompositeDisposable(params IDisposable[] disposables)
		{
			if (disposables == null)
			{
				throw new ArgumentNullException("disposables");
			}
			this._disposables = new List<IDisposable>(disposables);
			this._count = this._disposables.Count;
		}

		// Token: 0x06000A89 RID: 2697 RVA: 0x00038414 File Offset: 0x00036814
		public CompositeDisposable(IEnumerable<IDisposable> disposables)
		{
			if (disposables == null)
			{
				throw new ArgumentNullException("disposables");
			}
			this._disposables = new List<IDisposable>(disposables);
			this._count = this._disposables.Count;
		}

		// Token: 0x170000D0 RID: 208
		// (get) Token: 0x06000A8A RID: 2698 RVA: 0x00038460 File Offset: 0x00036860
		public int Count
		{
			get
			{
				return this._count;
			}
		}

		// Token: 0x06000A8B RID: 2699 RVA: 0x00038468 File Offset: 0x00036868
		public void Add(IDisposable item)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}
			bool flag = false;
			object gate = this._gate;
			lock (gate)
			{
				flag = this._disposed;
				if (!this._disposed)
				{
					this._disposables.Add(item);
					this._count++;
				}
			}
			if (flag)
			{
				item.Dispose();
			}
		}

		// Token: 0x06000A8C RID: 2700 RVA: 0x000384EC File Offset: 0x000368EC
		public bool Remove(IDisposable item)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}
			bool flag = false;
			object gate = this._gate;
			lock (gate)
			{
				if (!this._disposed)
				{
					int num = this._disposables.IndexOf(item);
					if (num >= 0)
					{
						flag = true;
						this._disposables[num] = null;
						this._count--;
						if (this._disposables.Capacity > 64 && this._count < this._disposables.Capacity / 2)
						{
							List<IDisposable> disposables = this._disposables;
							this._disposables = new List<IDisposable>(this._disposables.Capacity / 2);
							foreach (IDisposable disposable in disposables)
							{
								if (disposable != null)
								{
									this._disposables.Add(disposable);
								}
							}
						}
					}
				}
			}
			if (flag)
			{
				item.Dispose();
			}
			return flag;
		}

		// Token: 0x06000A8D RID: 2701 RVA: 0x0003861C File Offset: 0x00036A1C
		public void Dispose()
		{
			IDisposable[] array = null;
			object gate = this._gate;
			lock (gate)
			{
				if (!this._disposed)
				{
					this._disposed = true;
					array = this._disposables.ToArray();
					this._disposables.Clear();
					this._count = 0;
				}
			}
			if (array != null)
			{
				foreach (IDisposable disposable in array)
				{
					if (disposable != null)
					{
						disposable.Dispose();
					}
				}
			}
		}

		// Token: 0x06000A8E RID: 2702 RVA: 0x000386B8 File Offset: 0x00036AB8
		public void Clear()
		{
			IDisposable[] array = null;
			object gate = this._gate;
			lock (gate)
			{
				array = this._disposables.ToArray();
				this._disposables.Clear();
				this._count = 0;
			}
			foreach (IDisposable disposable in array)
			{
				if (disposable != null)
				{
					disposable.Dispose();
				}
			}
		}

		// Token: 0x06000A8F RID: 2703 RVA: 0x0003873C File Offset: 0x00036B3C
		public bool Contains(IDisposable item)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}
			object gate = this._gate;
			bool result;
			lock (gate)
			{
				result = this._disposables.Contains(item);
			}
			return result;
		}

		// Token: 0x06000A90 RID: 2704 RVA: 0x00038794 File Offset: 0x00036B94
		public void CopyTo(IDisposable[] array, int arrayIndex)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			if (arrayIndex < 0 || arrayIndex >= array.Length)
			{
				throw new ArgumentOutOfRangeException("arrayIndex");
			}
			object gate = this._gate;
			lock (gate)
			{
				List<IDisposable> list = new List<IDisposable>();
				foreach (IDisposable disposable in list)
				{
					if (disposable != null)
					{
						list.Add(disposable);
					}
				}
				Array.Copy(list.ToArray(), 0, array, arrayIndex, array.Length - arrayIndex);
			}
		}

		// Token: 0x170000D1 RID: 209
		// (get) Token: 0x06000A91 RID: 2705 RVA: 0x0003885C File Offset: 0x00036C5C
		public bool IsReadOnly
		{
			get
			{
				return false;
			}
		}

		// Token: 0x06000A92 RID: 2706 RVA: 0x00038860 File Offset: 0x00036C60
		public IEnumerator<IDisposable> GetEnumerator()
		{
			List<IDisposable> list = new List<IDisposable>();
			object gate = this._gate;
			lock (gate)
			{
				foreach (IDisposable disposable in this._disposables)
				{
					if (disposable != null)
					{
						list.Add(disposable);
					}
				}
			}
			return list.GetEnumerator();
		}

		// Token: 0x06000A93 RID: 2707 RVA: 0x000388F8 File Offset: 0x00036CF8
		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}

		// Token: 0x170000D2 RID: 210
		// (get) Token: 0x06000A94 RID: 2708 RVA: 0x00038900 File Offset: 0x00036D00
		public bool IsDisposed
		{
			get
			{
				return this._disposed;
			}
		}

		// Token: 0x040006E3 RID: 1763
		private readonly object _gate = new object();

		// Token: 0x040006E4 RID: 1764
		private bool _disposed;

		// Token: 0x040006E5 RID: 1765
		private List<IDisposable> _disposables;

		// Token: 0x040006E6 RID: 1766
		private int _count;

		// Token: 0x040006E7 RID: 1767
		private const int SHRINK_THRESHOLD = 64;
	}
}
